#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <alloc.h>

FILE *fPub;
int CurrPubRecNum=0;
char SearchedPubCode[7];
char SearchedPubName[21];
int TotalPubNode=0;

int TotalPubNum;

void SearchBypublisherCode();
void SearchBypublisherName();
void AddpublisherRecord();
void AmendpublisherRecord();
void DisplaySearchedPubRecord();
void OpenPubFile();
void ClosePubFile();
bool SearchPub();
bool WriteNewPubRecord();
void displayMenu();



void LoadPubRecord(struct PubRefer **q);
void AssignPubRefer(struct PubRefer **q);
void AddPubNode(struct PubRefer **q, int num);

/*===================== =====decare function upon===================================================*/

struct PubRefer
{
	 char PubCode[7];
	 char PubName[21];
	 struct PubRefer *publink;
};
struct PubRefer *mypubrefer;
/*---------------------====================================================----------------------------*/

struct Publisher
{
	 char PubCode[7];
	 char PubName[21];
	 char PubAddress[21];
};
struct Publisher pub;

/*==============================================================================*/
int main()
{

	 mypubrefer=(struct PubRefer*)malloc(sizeof(struct PubRefer));
	 LoadPubRecord(&mypubrefer);

	 bool isExit=false;

	 while (!isExit){

	 displayMenu();
	 char ch;
	 gets(&ch);
	 switch (ch){
		 case '1':
				  SearchBypublisherCode();

				  break;
		 case '2':
				  SearchBypublisherName();

				  break;
		 case '3':
				  AddpublisherRecord();

				  break;
		 case '4':
				  AmendpublisherRecord();

				  break;
		 case '5':
				  isExit=true;

		 }
		 
	 }
  return 0;
}

/*===============================publisher sub menu upon================================================*/
void displayMenu(){

	 puts("\n\nif you want to search a publisher by publisher code, please enter 1:");
	 puts("if you want to search a publisher by publisher name, please enter 2:");
	 puts("if you want to add a new publisher record, please enter 3:");
	 puts("if you want to amend a publisher record, please enter 4:");
	 puts("if you want to exit, please enter 5:");
	 puts("if you enter a wrong number, you have to restart the program.");


}
/*=============================================================================================*/
void SearchBypublisherCode()
{    int a;
	  OpenPubFile();
	  puts("please enter publisher code for the record you want to search./n");
	  gets(SearchedPubCode);

	  if (SearchPub()){
		  DisplaySearchedPubRecord();
		  ClosePubFile();

			 return;
		  }
	  else
		  {printf("not found, retry.");

		
			return;
		  }

 }
/*=======================function search by publisher code upon==========================================================*/
void DisplaySearchedPubRecord()
{
 long offset;
		puts("fallowing is the searched record details.");


		offset=sizeof(pub)* CurrPubRecNum;
		fseek(fPub, offset, 0);
		fread(&pub, sizeof(pub), 1, fPub);
		puts(pub.PubCode);
		puts(pub.PubName);
		puts(pub.PubAddress);
		puts("/n");

}
/*================================function DisplaySearchedPubRecord upon===============================================*/

void AddpublisherRecord()
{
	 puts("enter new publisher code");
	 gets(SearchedPubCode);
	 OpenPubFile();
	 while(true){
	 if  (SearchPub())
		 {
		  printf("this record has exited in file, retry./n");
		  puts("enter new publisher code");
		  gets(SearchedPubCode);
		 }
	 else
		 {
		  if (WriteNewPubRecord())
			  {
			  AddPubNode(&mypubrefer, TotalPubNode);
			  fclose(fPub);
			  return;
			  }
		  else
			  {fclose(fPub);
			  return;
								  }
		 }
	 }
}
/*=====================function add publisher record upon=========================================================*/

bool WriteNewPubRecord()
{
	  long offset;
	  char temp_name[21];
	  char temp_address[21];


	  offset=sizeof(pub)* TotalPubNode;
	  fseek(fPub, offset, 0);

	  fflush(stdin);
	  if(strlen(SearchedPubCode)>0 & strlen(SearchedPubCode)< 7 )
			strcpy(pub.PubCode, SearchedPubCode);
	  else
		  {puts("enterd publisher code is not valid, process fail.");
			return false;
			}


		puts("enter new value for publisher name./n");
		gets(temp_name);
		if (strlen(temp_name)>0 & strlen(temp_name)<21)
			strcpy(pub.PubName, temp_name);
		else
			{
			 puts("entered pub name is not valid. process fail.");
			 return false;
			 }


		puts("enter new address for publisher address./n");
		gets(temp_address);
		if(strlen(temp_address)>0 & strlen(temp_address)<21)
			strcpy(pub.PubAddress, temp_address);
		else
			 {puts("entered address is not valid, process fail.");
			 return false;
			 }

		fwrite(&pub, sizeof(pub), 1, fPub);
		TotalPubNum+=1;
		puts("new record is successfully added.");
		return true;

}
/*============================function write new publisher record upon==================================================*/

void AmendpublisherRecord()
{
	  int a;
	  long offset;
	  char temp_name[21];
	  char temp_address[21];





	  fflush(stdin);
	  puts("enter  publisher code for record you want to amend");
	  gets(SearchedPubCode);
		OpenPubFile();
	 // while(true){
	  if (SearchPub())
		  {
		  fPub=fopen("a:\\publisher.txt", "r+");
		  offset=sizeof(pub)* CurrPubRecNum;
			fseek(fPub, offset, 0);
			fread(&pub, sizeof(pub), 1, fPub);
			puts("change record now./n");

			puts(pub.PubName);
			puts("enter new value for publisher name./n");
			gets(temp_name);
			if(strlen(temp_name)>0)
				strcpy(pub.PubName, temp_name);

			puts(pub.PubAddress);
			puts("enter new value for publisher address./n");
			gets(temp_address);
			if(strlen(temp_address)>0)
				strcpy(pub.PubAddress, temp_address);
			fseek(fPub, offset, 0);
			fwrite(&pub, sizeof(pub),1,fPub);
			fflush(stdin);
			puts("amend record successful.");
			ClosePubFile();
			LoadPubRecord(&mypubrefer);
			}
	  else
			{
			printf("not found, retry.");
			//puts("enter  publisher code for record you want to amend");
		//	gets(SearchedPubCode);
			}
	 // }
}
/*========================function AmentPublisherRecord upon=====================================================*/
bool SearchPub()
{
  int index=0;
	struct PubRefer *temp;
	temp=mypubrefer;
  if (TotalPubNode==0)
		{puts("not found");
		return false;
		}
  while (index<TotalPubNode)
	  {

		  if  (strcmp(SearchedPubCode,temp->PubCode)==0)
		  {     CurrPubRecNum=index;
			return true;
		  }
		  else
				{index+=1;
				 temp=temp->publink;
				}
	  }

	  return false;
}
/*========================function search upon======================================================*/
 void SearchBypublisherName()
{
	 int index=0;
	  struct PubRefer *temp;
	  temp=mypubrefer;
	  CurrPubRecNum=0;

	  OpenPubFile();
	  puts("please enter publisher name for the record you want to search./n");
	  gets(SearchedPubName);
  if  (TotalPubNode==0  )
		{ puts("not found");
                  fclose(fPub);
		 return;}
	while (index<=TotalPubNode)
		{
			  if   (strcmp(SearchedPubName, temp->PubName)==0)
			  {
					 CurrPubRecNum= index;
					 DisplaySearchedPubRecord();
					  index+=1;
					 temp=temp->publink;
			  }
			  else
			  {
					 index+=1;
					 temp=temp->publink;
			  }
		}
puts("if no result show, that means searched publisher name is not exist.");
fclose(fPub);
}

/*=================================================*/
void OpenPubFile()
{

	 fPub=fopen("a:\\publisher.txt", "r+" );
         if (fPub==0)
         {
          puts("publisher file is not existed, create one? please insert a floppy disk.");
          fPub=fopen("a:\\publisher.txt", "w" );
          fclose(fPub);
          fPub=fopen("a:\\publisher.txt", "r+" );
         }

}
/*=================open pub file==================================*/
void ClosePubFile()
{
	  fclose(fPub);
}

/*=====================close pub file===================================*/
void  LoadPubRecord(struct PubRefer **q)
{

	long offset;
	struct PubRefer *temp;
	temp=*q;

	TotalPubNode=0;
	OpenPubFile();


			 while(true)
			 {
			 if (fread(&pub, sizeof(pub),1,fPub)==1)
				 {
					 if (temp==NULL)
						  {   temp=(struct PubRefer*)malloc(sizeof(struct PubRefer));

								AssignPubRefer(&temp);

							}
					 else {
							 temp->publink=(struct PubRefer*)malloc(sizeof(struct PubRefer) );
							 temp=temp->publink;
							 AssignPubRefer(&temp);
							}
				 }
			 else
				 {
						ClosePubFile();
						break;
				 }
			}
		 return;
		 }
	/* catch (const exception& e)
	 {
		cout << "Got an exception: " << e.what() << endl;
		ClosePubFile();
	 }
		*/

/*======================load publisher code to array===================================================*/
void AssignPubRefer(struct PubRefer **p)
{
	  struct PubRefer *temp;
	  temp=*p;

	  long offset=sizeof(pub)*TotalPubNode;
	  fseek(fPub, offset, 0);
	  fread(&pub, sizeof(pub), 1,fPub);
	  strcpy(temp->PubCode, pub.PubCode);
	  strcpy(temp->PubName,pub.PubName );
	  TotalPubNode+=1;
	  return;
}
/*=======================Assign Pub Refer================================*/
void AddPubNode(struct PubRefer **q, int num)
{

	  int index;
	  struct PubRefer *temp;
	 
	  
		  if (TotalPubNode==0 || *q==NULL)
		  {
			  *q=(struct PubRefer*)malloc(sizeof(struct PubRefer));
			  temp=*q;
			  AssignPubRefer(&temp);
			  return;
		  }
		  else
		  {
				while(index<=TotalPubNode)
				{
				temp=temp->publink;
				}
				temp=(struct PubRefer*)malloc(sizeof(struct PubRefer) );
				AssignPubRefer(&temp);

		  }
		  return;
}
/*===========================================================*/

 

 
